﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Timers;

namespace intelliSys.UI.Interaction.MouseGesture
{
    /// <summary>
    /// <para>This one uses a re-enerable timer to detect Hold Gesture.</para>
    /// <para>Hold gesture is defined as follow:</para>
    /// <para>*Mouse left button is down for a specified amount of time</para>
    /// <para>*Mouse is motionless</para>
    /// </summary>
    public class Hold : MouseGestureBase
    {
        /// <summary>
        /// How long in seconds should the mouse be pressed in motionless state before the gesture is detected.
        /// <para>This is not always accurate since this gesture is detected using a timer rather than a thread. Accuracy varies according to hardware.</para>
        /// <para>THIS IMPLEMENTATION IS SUBJECT TO CHANGE</para>
        /// </summary>
        public int HoldDuration
        {
            get
            {
                return holdDuration;
            }
            set
            {
                holdDuration = value;
            }
        }
        public override event EventHandler<MouseGestureEventArgBase> OnSensed;
        int holdDuration = 1;
        DateTime startingTime;
        Win32.Point startingPt;

        public Hold(Window window)
            : base(window)
        {
            window.PreviewMouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(window_PreviewMouseLeftButtonDown);
            window.PreviewMouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(window_PreviewMouseLeftButtonUp);
            tmr.Elapsed += new ElapsedEventHandler(tmr_Elapsed);
        }

        void tmr_Elapsed(object sender, ElapsedEventArgs e)
        {
            Win32.Point pt;
            Win32.GetCursorPos(out pt);
            if(pt.X!=startingPt.X || pt.Y!=startingPt.Y)
            {
                ClrState();
            }
            if ((DateTime.Now - startingTime).TotalSeconds >= holdDuration)
            {
                ClrState();
                if (InstantFire)
                {

                    wnd.Dispatcher.BeginInvoke(new Action(() =>
                        {
                            OnSensed(this, new HoldEventArg() { InstantFired = true });
                        }));
                }
                else
                {
                    fire = true;
                }
            }
        }

        void window_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (fire)
            {
                wnd.Dispatcher.BeginInvoke(new Action(() =>
                {
                    OnSensed(this, new HoldEventArg() { InstantFired = false });
                }));
            }
            ClrState();
        }

        void window_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            startingTime = DateTime.Now;
            Win32.GetCursorPos(out startingPt);
            tmr.Start();
        }

        void ClrState()
        {
            tmr.Enabled = false;
            fire = false;
        }
    }

    public class HoldEventArg : MouseGestureEventArgBase
    {
    }
}
